package com.zc.auth.security.core.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.util.IOUtils;
import com.zc.auth.security.core.authentication.AuthenticationTokenService;
import com.zc.commons.http.entity.Response;
import com.zc.context.authentication.ctx.AuthenticationContext;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 基于Servlet的过滤器
 */
public class ServletAuthenticationFilter extends BasicAuthenticationFilter {

    private AuthenticationTokenService tokenService;

    public ServletAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }

    public ServletAuthenticationFilter tokenService(AuthenticationTokenService tokenService) {
        this.tokenService = tokenService;
        return this;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {

        String authorization = request.getHeader(HttpHeaders.AUTHORIZATION);
        try {
            Authentication authentication = tokenService.getAuthentication(authorization);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            AuthenticationContext.setCurrentAuthUser(tokenService.getPrincipal(authentication));
        } catch (AuthenticationException e) {
            SecurityContextHolder.clearContext();
            AuthenticationContext.clearCurrentAuthUser();
            this.onUnsuccessfulAuthentication(request, response, e);
            return;
        }
        chain.doFilter(request, response);
    }

    @Override
    protected void onUnsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException ex) throws IOException {
        // 只处理token问题 要求登录
        response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");
        String dataString = JSON.toJSONString(Response.error(ex.getMessage()), SerializerFeature.WriteMapNullValue);
        PrintWriter printWriter = response.getWriter();
        printWriter.write(dataString);
        IOUtils.close(printWriter);
    }
}
